/****************************************************************************************
 * File:			Interface.cs
 * Description:		Definition of an interface and helper classes.
 ***************************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace XGAE.Framework
{
    /// <summary>
    /// Base class from which any implementation of a virtual interface must derive.  Provides 
    /// essential information and functionality for querying versions.
    /// </summary>
    public class Interface
    {
        #region Fields

        Component _listener; // passing messages to the parent component

        private int	_version; // interface specification revision number

        /// <summary>
        /// Wrappers to access the interface version.
        /// </summary>
        public int Version
        {
            get{ return this._version; }            
        }

	    string _name; // string representing the interface type

        /// <summary>
        /// Get the interface's type.
        /// </summary>
        public string Name
        {
            get{ return this._name; }
        }

        #endregion

        #region C'tors

        /// <summary>
        /// Constructor called by the class factory when it creates a new interface.
        /// </summary>
        /// <param name="name">String representing the type of the interface.</param>
        /// <param name="version">Version of this interface, major & minor revisions.</param>
	    public Interface( string name, int version )
	    {
            this._name = name;
            this._version = version;
            this._listener = null;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Send a message directly to the parent component in asynchronous fashion.
        /// </summary>
        /// <param name="message">A message that must be sent, it needs downcasting. </param>
	    public void Dispatch( Message message )
	    {
		    if (this._listener!=null)
			    this._listener.Dispatch( message );
	    }

        /// <summary>
        /// Used by the parent component to alert the interface it requires messages.
        /// </summary>
        /// <param name="component"></param>
	    public void RegisterListener( Component component )
	    {
		    this._listener = component;
	    }

    	/// <summary>
    	/// Check if two interface versions are compatible.  This can be called without an 
        /// interface instance, thanks to the static definition.  The function is inlined so
        /// that the function call is optimized out.
    	/// </summary>
        /// <param name="version">Version to test.</param>
        /// <param name="refVersion">Reference version to compare it to.</param>
    	/// <returns></returns>
        public static bool IsCompatible( int version, int refVersion )
        {
            // major version must match
            return (version >> 16) == (refVersion >> 16)
            // and provide a better minor version
            && (version & 0xff) >= (refVersion & 0xff);
        }

        #endregion

        /// <summary>
        /// Wrapper to set the interface version.
        /// </summary>
        /// <param name="v"></param>
        protected void SetVersion(int v)
        {
            this._version = v;
        }
    }

    /// <summary>
    /// Base class from which all message data-structures are derived.
    /// </summary>
    public class Message
    {
        private string _type; // the basic type of this message

        public string Type
        {
            get { return this._type; }
        }

        //private ushort _numType; // numerical identifier of messages

        public Message(string t)
        {
            this._type = t;
        }

        /*public static bool operator >(Message m1, Message m2)
        {
            return messageTaxonomy.IsSubtype(GetMessageType(m1.type), GetMessageType(m2.type));
        }

        public static bool operator <(Message m1, Message m2)
        {
            return !messageTaxonomy.IsSubtype(GetMessageType(m1.type), GetMessageType(m2.type));
        }*/

        public static bool operator ==(Message m1, Message m2)
        {
            return m1.Type == m2.Type;
        }

        public static bool operator !=(Message m1, Message m2)
        {
            return m1.Type != m2.Type;
        }

        public static bool operator >=(Message m1, Message m2)
        {
            return m1 == m2 /*|| m1 > m2*/;
        }

        public static bool operator <=(Message m1, Message m2)
        {
            return m1 == m2 /*|| m1 < m2*/;
        }

        public static bool operator >=(Message m, string s)
        {
            return m >= new Message(s);
        }

        public static bool operator <=(Message m, string s)
        {
            return m <= new Message(s);
        }
    }

}
